import { useCallback, useRef, useState } from "react";

interface Options {
  fileName: string; //下载的文件名
  onCompleted?: () => void; //请求完成的回调方法
  onError?: (error: Error) => void; //请求失败的回调方法
}

interface FileDownReturn {
  download: () => void; //下载
  cancel: () => void; //取消
  progress: number; //下载进度百分比
  isDownloading: boolean; //是否下载中
}

export default function useFileDown(
  url: string,
  options: Options
): FileDownReturn {
  const { fileName, onCompleted, onError } = options;
  const [progress, setProgress] = useState(0);
  const [isDownloading, setIsDownloading] = useState(false);
  const xhrRef = useRef<XMLHttpRequest | null>(null);

  const download = useCallback(() => {
    const xhr = (xhrRef.current = new XMLHttpRequest());
    xhr.open("GET", url); //默认异步请求
    xhr.responseType = "blob";
    xhr.onprogress = (e) => {
      //判断资源长度是否可计算
      if (e.lengthComputable) {
        const percent = Math.floor((e.loaded / e.total) * 100);
        setProgress(percent);
      }
    };
    xhr.onload = () => {
      if (xhr.status === 200) {
        //请求资源完成，将文件内容转为blob
        const blob = new Blob([xhr.response], {
          type: "application/octet-stream",
        });
        //通过a标签将资源下载
        const link = document.createElement("a");
        link.href = window.URL.createObjectURL(blob);
        link.download = decodeURIComponent(fileName);
        link.click();
        window.URL.revokeObjectURL(link.href);
        onCompleted && onCompleted();
      } else {
        onError && onError(new Error("下载失败"));
      }
      setIsDownloading(false);
    };
    xhr.onerror = () => {
      onError && onError(new Error("下载失败"));
      setIsDownloading(false);
    };
    xhrRef.current.send(); //发送请求
    setProgress(0); //每次发送时将进度重置为0
    setIsDownloading(true);
  }, [fileName, onCompleted, onError, url]);

  const cancel = useCallback(() => {
    xhrRef.current?.abort(); //取消请求
    setIsDownloading(false);
  }, [xhrRef]);

  return {
    download,
    cancel,
    progress,
    isDownloading,
  };
}
